/*
 * Title:        CloudScheduler Toolkit
 * Description:  a Toolkit for Modeling and Simulation of Job Scheduling and Resource Provisioning in Cloud System
 * Licence:      GPL - http://www.gnu.org/copyleft/gpl.html
 * Author:       Fuhui Wu
 *
 * Copyright (c) 2013-2014, The National University of Defense Technology, China
 */

package org.nudt.jCloud.workload;

import java.util.ArrayList;
import java.util.List;

import org.nudt.jCloud.simulation.CloudSchedSIM;
import org.nudt.jCloud.simulation.Request;
import org.nudt.jCloud.simulation.SIMTag;
import org.nudt.jCloud.util.Log;

public abstract class LogicalJob implements Comparable<LogicalJob>{
	private int id;
	private Workload wl;
	private List<Job> jobs;
	private double arrivalTime;
	private boolean submitted;
	private boolean finished;
	private int index = 0;				//used to set job id when a new job is added.
		
	public LogicalJob(double arrivalTime, Workload wl){
		setArrivalTime(arrivalTime);
		setWl(wl);
		jobs = new ArrayList<Job>();
		setSubmitted(false);
		setFinished(false);
	}
	
	public void submit(){
		setSubmitted(true);
		Log.println(getWl().getUser().getUserBroker().getName()+"    submit: "+this.type()+"-"
				+this.getId());
		Log.jobLog(getWl().getUser().getUserName(), CloudSchedSIM.getClock(), this.getId(), SIMTag.XJOB_SUBMIT);
		for(int i=0; i<getJobs().size(); ++i){
			Job job = getJobs().get(i);
			for(int j=0; j<job.getTaskList().size(); ++j){
				Log.taskLog(getWl().getUser().getUserName(), CloudSchedSIM.getClock(), 
						getId(), job.getId(), job.getTaskList().get(j).getId(), SIMTag.TASK_SUBMIT, -1, false);
			}
		}
	}
	
	public void update(){
		if(checkFinished()){
			setSubmitted(false);
			setFinished(true);
			Log.println(getWl().getUser().getUserBroker().getName()+"    finish "+type()+"-"+getId());
			Log.jobLog(getWl().getUser().getUserName(), CloudSchedSIM.getClock(), getId(), SIMTag.XJOB_FINISH);
		}
	}
	
	public abstract List<Request> request();
	public abstract boolean checkFinished();
	public abstract String type();
	
	/*
	 * add a new job to job list.
	 */
	public void add(Job job){
		jobs.add(job);
		job.setId(index++);
	}
	
	public void reset() {
		setSubmitted(false);
		setFinished(false);
		for(int i=0; i<jobs.size(); ++i){
			jobs.get(i).reset();
		}
		
	}
	
	@Override
	public int compareTo(LogicalJob xJob) {
		if(xJob == null){
			return 1;
		}else if(arrivalTime < xJob.getArrivalTime()){
			return -1;
		}else if(arrivalTime > xJob.getArrivalTime()){
			return 1;
		}else if(this == xJob){
			return 0;
		}else{
			return 1;
		}
	}

	public List<Job> getJobs() {
		return jobs;
	}

	public void setJobs(List<Job> jobs) {
		this.jobs = jobs;
	}

	public double getArrivalTime() {
		return arrivalTime;
	}

	public void setArrivalTime(double arrivalTime) {
		this.arrivalTime = arrivalTime;
	}

	public int getId() {
		return id;
	}

	public void setId(int id) {
		this.id = id;
	}

	public int getIndex() {
		return index;
	}

	public void setIndex(int index) {
		this.index = index;
	}

	public Workload getWl() {
		return wl;
	}

	public void setWl(Workload wl) {
		this.wl = wl;
	}

	public void setFinished(boolean finished) {
		this.finished = finished;
	}
	
	public boolean isFinished(){
		return finished;
	}

	public boolean isSubmitted() {
		return submitted;
	}

	public void setSubmitted(boolean submitted) {
		this.submitted = submitted;
	}
	
}
